/* 
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.appspot.dispotrains.station;

import com.google.common.collect.Maps;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;
import android.util.Pair;

import com.appspot.dispotrains.R;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

public class StationLister
    extends AsyncTaskLoader<Pair<HashMap<Integer, Line>, HashMap<Integer, Station>>> {
  private HashMap<Integer, Line> lines = Maps.newHashMap();
  private HashMap<Integer, Station> stations = Maps.newHashMap();

  /**
   * @param context
   */
  public StationLister(Context context) {
    super(context);
  }

  public void parseJson(String object) {
    try {
      JSONObject stationsJson = new JSONObject(object);
      JSONArray linesJson = stationsJson.getJSONArray("lines");
      for (int i = 0; i < linesJson.length(); i++) {
        String lineType = linesJson.getJSONObject(i).getString("reseau");
        String lineNumber = linesJson.getJSONObject(i).getString("ligne");
        int lineId = linesJson.getJSONObject(i).getInt("id");
        lines.put(lineId, new Line(lineId, lineType, lineNumber));
      }

      JSONArray stationList = stationsJson.getJSONArray("stations");
      for (int i = 0; i < stationList.length(); i++) {
        JSONObject jsonStation = stationList.getJSONObject(i);
        String name = jsonStation.getString("nom");
        Integer id = jsonStation.getInt("id");
        Station station = new Station(id, name);

        JSONArray stops = jsonStation.getJSONArray("arrets");
        for (int j = 0; j < stops.length(); j++) {
          station.addLine(lines.get(stops.getJSONObject(j).getInt("id")));
        }

        JSONArray infomobi = jsonStation.getJSONArray("infomobi");
        for (int j = 0; j < infomobi.length(); j++) {
          station.addInfomobiCode(infomobi.getInt(j));
        }
        stations.put(id, station);
      }
    } catch (JSONException e) {
      // Do nothing.
    }
  }

  // Given a URL, establishes an HttpUrlConnection and retrieves
  // the web page content as a InputStream, which it returns as
  // a string.
  private String downloadUrl(URL url) throws IOException {
    InputStream is = null;

    try {
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setReadTimeout(25000 /* milliseconds */);
      conn.setConnectTimeout(30000 /* milliseconds */);
      conn.setRequestMethod("GET");
      conn.setDoInput(true);
      // Starts the query
      conn.connect();
      int response = conn.getResponseCode();
      Log.d("StationListenerDownloader", "The response is: " + response);
      is = conn.getInputStream();

      // Convert the InputStream into a string
      String contentAsString = readIt(is);
      return contentAsString;

      // Makes sure that the InputStream is closed after the app is
      // finished using it.
    } finally {
      if (is != null) {
        is.close();
      }
    }
  }

  // Reads an InputStream and converts it to a String.
  public String readIt(InputStream is) throws IOException, UnsupportedEncodingException {
    BufferedReader br = new BufferedReader(new InputStreamReader(is));

    StringBuilder sb = new StringBuilder();

    String line;
    while ((line = br.readLine()) != null) {
      sb.append(line);
    }
    return sb.toString();
  }


  /**
   * @see android.content.AsyncTaskLoader#loadInBackground()
   */
  @Override
  public Pair<HashMap<Integer, Line>, HashMap<Integer, Station>> loadInBackground() {
    ConnectivityManager connMgr =
        (ConnectivityManager) this.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    if (networkInfo == null || !networkInfo.isConnected()) {
      return null;
    }

    String data;
    try {
      // data = downloadUrl(new
      // URL("http://sterops.pythonanywhere.com/json/GetGares"));
      data = readIt(getContext().getResources().openRawResource(R.raw.stationlist));
      parseJson(data);
      return Pair.create(lines, stations);
    } catch (MalformedURLException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * Handles a request to start the Loader.
   */
  @Override
  protected void onStartLoading() {
    if (stations.size() != 0 && !takeContentChanged()) {
      // If we currently have a result available, deliver it
      // immediately.
      deliverResult(Pair.create(lines, stations));
    } else {
      forceLoad();
    }
  }


  /**
   * Handles a request to stop the Loader.
   */
  @Override
  protected void onStopLoading() {
    // Attempt to cancel the current load task if possible.
    cancelLoad();
  }

  /**
   * Handles a request to cancel a load.
   */
  @Override
  public void onCanceled(Pair<HashMap<Integer, Line>, HashMap<Integer, Station>> stations) {
    super.onCanceled(stations);
  }

  @Override
  protected void onReset() {
    super.onReset();

    // Ensure the loader is stopped
    onStopLoading();
  }

}
